﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Model;
using Gma.UserActivityMonitor;
using System.Runtime.InteropServices;

namespace MouseAndKeyLogger
{
    public partial class GetEvents : Form
    {
        public GetEvents()
        {
            InitializeComponent();
        }

        int count = 2;
        int width_orig = SystemInformation.VirtualScreen.Width;
        int height_orig = SystemInformation.VirtualScreen.Height;
        System.Threading.Thread thread = null;

        int count_eventos = 0;

        List<Evento> eventos = new List<Evento>();
        DateTime dtInicio = DateTime.Now;

        // Get a handle to an application window.
        [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);

        // Activate an application window.
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

        [DllImport("user32.dll")]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

        [DllImport("user32.dll")]
        private static extern short VkKeyScan(char ch); 


        const int MOUSEEVENTF_MOVE = 0x00000001;
        const int MOUSEEVENTF_LEFTDOWN = 0x00000002;
        const int MOUSEEVENTF_LEFTUP = 0x00000004;
        const int MOUSEEVENTF_RIGHTDOWN = 0x00000008;
        const int MOUSEEVENTF_RIGHTUP = 0x00000010;
        const int MOUSEEVENTF_MIDDLEDOWN = 0x00000020;
        const int MOUSEEVENTF_MIDDLEUP = 0x00000040;
        const int MOUSEEVENTF_WHEEL = 0x00000800;
        const int MOUSEEVENTF_ABSOLUTE = 0x00008000;

        public int tempHeight;
        public int tempWidth;

        private void btnInicio_Click(object sender, EventArgs e)
        {
            //HookManager.KeyPress += new KeyPressEventHandler(HookManager_KeyPress);
            HookManager.MouseClick += new MouseEventHandler(HookManager_MouseClick);
            HookManager.KeyDown += new KeyEventHandler(HookManager_KeyDown);
            HookManager.KeyUp += new KeyEventHandler(HookManager_KeyUp);



            //Screen Srn = Screen.PrimaryScreen;
            //tempHeight = Srn.Bounds.Height;
            //tempWidth = Srn.Bounds.Width;

            //new Model.Resolution.CResolution(1024, 768);

        }

        void HookManager_KeyUp(object sender, KeyEventArgs e)
        {
            count_eventos++;

            MostrarEvento();

            eventos.Add(new Evento()
            {
                TipoEvento = TipoEvento.Keyboard,
                Tecla = (int)e.KeyValue,
                Diferenca = DateTime.Now.Subtract(dtInicio).TotalMilliseconds,
                TipoKey = TipoKey.Up,
                dataEvento = DateTime.Now
            });

            dtInicio = DateTime.Now;
        }

        void HookManager_KeyDown(object sender, KeyEventArgs e)
        {
            count_eventos++;

            MostrarEvento();

           eventos.Add(new Evento()
            {
                TipoEvento = TipoEvento.Keyboard,
                Tecla = (int)e.KeyValue,
                Diferenca = DateTime.Now.Subtract(dtInicio).TotalMilliseconds,
                TipoKey = TipoKey.Down,
                dataEvento = DateTime.Now

            });

            dtInicio = DateTime.Now;
        }

        

        void HookManager_MouseClick(object sender, MouseEventArgs e)
        {

            

            if(count % 2 == 0)
            {

                count_eventos++;
                MostrarEvento();

                if(e.Button == MouseButtons.Left)
                    eventos.Add(new Evento()
                    {
                        PointX = e.X,
                        PointY = e.Y,
                        TipoBotao = TipoBotao.Esquerdo,
                        TipoEvento = TipoEvento.Mouse,
                        Diferenca = DateTime.Now.Subtract(dtInicio).TotalMilliseconds,
                        dataEvento = DateTime.Now

                    });
                else if(e.Button == MouseButtons.Right)
                {
                    eventos.Add(new Evento()
                    {
                        PointX = e.X,
                        PointY = e.Y,
                        TipoBotao = TipoBotao.Direito,
                        TipoEvento = TipoEvento.Mouse,
                        Diferenca = DateTime.Now.Subtract(dtInicio).TotalMilliseconds,
                        dataEvento = DateTime.Now

                    });

                }
            }
            count++;
            dtInicio = DateTime.Now;
        }

        //void HookManager_KeyPress(object sender, KeyPressEventArgs e)
        //{
           
            
        //}

        private void MostrarEvento()
        {
            notifyIcon1.Text = "Gravando Evento:" + count_eventos;
            notifyIcon1.ShowBalloonTip(1000, "EVENTO GERADO", "Gravando Evento:" + count_eventos, ToolTipIcon.Info);
        }

        private void btnParar_Click(object sender, EventArgs e)
        {
            //HookManager.KeyPress -= new KeyPressEventHandler(HookManager_KeyPress);
            HookManager.MouseClick -= new MouseEventHandler(HookManager_MouseClick);
            HookManager.KeyDown -= new KeyEventHandler(HookManager_KeyDown);
            HookManager.KeyUp -= new KeyEventHandler(HookManager_KeyUp);

            //new Model.Resolution.CResolution(tempWidth, tempHeight);

            this.eventos.RemoveAt(this.eventos.Count - 1);
            this.eventos.RemoveAt(this.eventos.Count - 1);


            foreach(Evento evento in eventos)
            {
                txtLogs.Text += ApresentaEvento(evento);
            }
        }

        private void btnResgatar_Click(object sender, EventArgs e)
        {
            foreach(Evento evento in eventos)
            {
                txtLogs.Text += ApresentaEvento(evento);
            }
        }

        private string ApresentaEvento(Evento evento)
        {
            string retorno = string.Empty;

            retorno += (evento.TipoEvento == TipoEvento.Keyboard) ? "Keyboard - " : "";
            retorno += (evento.TipoEvento == TipoEvento.Mouse) ? "Mouse - " : "";
            retorno += (evento.TipoEvento == TipoEvento.PrintScreen) ? "PrintScreen - " : "";

            if(evento.TipoEvento == TipoEvento.Keyboard)
            {
                retorno += "Tecla:" + evento.Tecla.ToString() + " - Diferenca=" + evento.Diferenca + Environment.NewLine;
            }

            if(evento.TipoEvento == TipoEvento.Mouse)
            {
                retorno += "Mouse:X=" + evento.PointX.ToString() + ",Y=" + evento.PointY.ToString() + ",Tipo=" + ProcessaTipo(evento.TipoBotao) + " - Diferenca=" + evento.Diferenca + Environment.NewLine;
            }

            if (evento.TipoEvento == TipoEvento.PrintScreen)
            {
                retorno += "PrintScreen:Diferenca=" + evento.Diferenca + Environment.NewLine;
            }

            return retorno;
        }

        private string ProcessaTipo(TipoBotao tipoBotao)
        {
            string retorno = string.Empty;
            switch(tipoBotao)
            {
                case TipoBotao.Direito:
                    retorno = "Botão Direito";
                    break;
                case TipoBotao.Esquerdo:
                    retorno = "Botão Esquerdo";
                    break;
                case TipoBotao.DuploEsquerdo:
                    retorno = "Botão Duplo Esquerdo";
                    break;
                case TipoBotao.DuploDireito:
                    retorno = "Botão Duplo Direito";
                    break;
                default:
                    break;
            }

            return retorno;
        }

        private void btnWriteXML_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog(this);


            DataSet ds = new DataSet();

            DataTable dt = new DataTable();
            dt.Columns.Add("TipoEvento");
            dt.Columns.Add("PointX");
            dt.Columns.Add("PointY");
            dt.Columns.Add("TipoBotao");
            dt.Columns.Add("Tecla");
            dt.Columns.Add("Diferenca");
            dt.Columns.Add("Width");
            dt.Columns.Add("Height");
            dt.Columns.Add("TipoKey");

            foreach(Evento evento in eventos)
            {

                DataRow dr = dt.NewRow();
                dr["TipoEvento"] = evento.TipoEvento;
                dr["PointX"] = evento.PointX;
                dr["PointY"] = evento.PointY;
                dr["TipoBotao"] = evento.TipoBotao;
                dr["Tecla"] = evento.Tecla;
                dr["Diferenca"] = evento.Diferenca;
                dr["Width"] = SystemInformation.VirtualScreen.Width;
                dr["Height"] = SystemInformation.VirtualScreen.Height;
                dr["TipoKey"] = evento.TipoKey;
                dt.Rows.Add(dr);

            }

            ds.Tables.Add(dt);
            ds.WriteXml(saveFileDialog1.FileName, XmlWriteMode.WriteSchema);
        }

        private void btnProcurar_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog(this);

            //lê o xml

            DataSet ds = new DataSet();
            ds.ReadXml(openFileDialog1.FileName, XmlReadMode.ReadSchema);


            foreach(DataRow dr in ds.Tables[0].Rows)
            {
                Evento evento = new Evento();
                evento.Diferenca = Convert.ToDouble(dr["Diferenca"]);
                if(dr["PointX"] != null && dr["PointX"] != DBNull.Value)
                    evento.PointX = Convert.ToInt32(dr["PointX"]);

                if(dr["PointY"] != null && dr["PointY"] != DBNull.Value)
                    evento.PointY = Convert.ToInt32(dr["PointY"]);

                if(dr["Tecla"] != null && dr["Tecla"] != DBNull.Value)
                    evento.Tecla = Convert.ToInt32(dr["Tecla"]);

                evento.TipoBotao = TraduzBotao(dr["TipoBotao"]);
                evento.TipoEvento = TraduzEvento(dr["TipoEvento"]);

                eventos.Add(evento);


                width_orig = Convert.ToInt32(dr["Width"]);
                height_orig = Convert.ToInt32(dr["Height"]);
            }

            
        }

        private TipoEvento TraduzEvento(object p)
        {
            if(p.ToString() == "Mouse")
                return TipoEvento.Mouse;
            else
                return TipoEvento.Keyboard;
        }

        private TipoBotao TraduzBotao(object p)
        {
            if(p.ToString() == "Esquerdo")
                return TipoBotao.Esquerdo;
            else if(p.ToString() == "Direito")
                return TipoBotao.Direito;
            else if(p.ToString() == "DuploEsquerdo")
                return TipoBotao.DuploEsquerdo;
            else if(p.ToString() == "DuploDireito")
                return TipoBotao.DuploDireito;
            else
                return TipoBotao.Direito;

        }

        private void btnExecutar_Click(object sender, EventArgs e)
        {
            //Screen Srn = Screen.PrimaryScreen;
            //tempHeight = Srn.Bounds.Width;
            //tempWidth = Srn.Bounds.Height;

            //new Model.Resolution.CResolution(1024, 768);


            thread = new System.Threading.Thread(new System.Threading.ThreadStart(ExecutaPassos));
            thread.Start();


            while(thread.IsAlive)
                System.Threading.Thread.Sleep(1000);

            //new Model.Resolution.CResolution(tempWidth, tempHeight);
        }

        private void ExecutaPassos()
        {
            //regra de tres para saber qual o tamanho da tela

            int width = SystemInformation.VirtualScreen.Width;
            int height = SystemInformation.VirtualScreen.Height;


            double mult_width = Convert.ToDouble(width) / Convert.ToDouble(width_orig);
            double mult_height = Convert.ToDouble(height) / Convert.ToDouble(height_orig);



            count_eventos = eventos.Count;

            int count_evento = 0;


            notifyIcon1.ShowBalloonTip(1000, "PREPARANDO EVENTO", "Aguarde início da execução", ToolTipIcon.Info);

            foreach(Evento evento in eventos)
            {
                if(count_evento == 0)
                    evento.Diferenca = 10000;

                System.Threading.Thread.Sleep(Convert.ToInt32(evento.Diferenca));

                #region Mouse
                if(evento.TipoEvento == TipoEvento.Mouse)
                {
                    
                    double meio_orig_width = evento.PointX -  (Convert.ToDouble(width_orig) / 2);
                    double novo_ponto_width = (Convert.ToDouble(width) / 2) + meio_orig_width;

                    double meio_orig_height = evento.PointY - (Convert.ToDouble(height_orig) / 2);
                    double novo_ponto_height = (Convert.ToDouble(height) / 2) + meio_orig_height;



                    Cursor.Position = new Point(Convert.ToInt32(novo_ponto_width), Convert.ToInt32(novo_ponto_height));

                    

                    switch(evento.TipoBotao)
                    {
                        case TipoBotao.Direito:
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.Esquerdo:
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.DuploEsquerdo:
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
                            break;
                        case TipoBotao.DuploDireito:
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
                            mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
                            break;
                        default:
                            break;
                    }
                }
                #endregion

                #region Keyboard

                if(evento.TipoEvento == TipoEvento.Keyboard)
                {
                    Char c = (Char)evento.Tecla;
                    short num = VkKeyScan(c);
                    keybd_event((byte)num, 0x45, 0, 0);
                    keybd_event((byte)num, 0x45, 2, 0);




                    //byte[] teste = BitConverter.GetBytes(evento.Tecla);
                }

                #endregion

                count_evento++;

                //executando evento
                notifyIcon1.ShowBalloonTip(1000, "EXECUTANDO EVENTO", "Executando evento " + count_evento + " de " + count_eventos, ToolTipIcon.Info);
            }

            notifyIcon1.ShowBalloonTip(1000, "FINALIZANDO EVENTOS", "Eventos finalizados com sucesso!", ToolTipIcon.Info);
        }

        public string ConvertToHex(string asciiString)
        {
            string hex = "";
            foreach(char c in asciiString)
            {
                int tmp = c;
                hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
            }
            return hex;
        }

        private void GetEvents_Load(object sender, EventArgs e)
        {
            
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            //parar execução
            if(thread != null)
                thread.Abort();

            thread = null;

            notifyIcon1.ShowBalloonTip(1000, "EXECUÇÂO ABORTADA", "Execução abortada pelo usuário!", ToolTipIcon.Info);
        }

        private void btnDock_Click(object sender, EventArgs e)
        {
            //this.Hide();
            //DockableMenu menu = new DockableMenu();
            //menu.Location = new Point(0, 100);
            //menu.Show();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            count = 2;
            count_eventos = 0;
            eventos = new List<Evento>();
            txtLogs.Text = string.Empty;
        }

        private void btnTirarPrint_Click(object sender, EventArgs e)
        {
            double diferenca = DateTime.Now.Subtract(this.eventos[this.eventos.Count - 3].dataEvento).TotalMilliseconds;

            this.eventos.RemoveAt(this.eventos.Count - 1);
            this.eventos.RemoveAt(this.eventos.Count - 1);

            //colocar o evento de PrintScreen
            this.eventos.Add(new Evento() { TipoEvento = TipoEvento.PrintScreen, Diferenca = diferenca });

            dtInicio = DateTime.Now;
        }
    }
}
